#pragma once 
#include "dp.hpp"
#include "match.hpp"
#include "online.hpp"
#include "room.hpp"
#include "session.hpp"
#include "Util.hpp"
#define WWWROOT "./webroot/"
class gomoku_server
{
    private:
        std::string _web_root;//静态网页资源 ./wwwroot/
        websocketsvr _websock;//web服务器管理   实例 _websock 就是一个 WebSocket 服务器对象，它可以使用 ASIO 库来处理网络通信。这个对象将用于管理 WebSocket 服务器的状态，
        //包括启动服务器、接受客户端连接、处理 WebSocket 消息、关闭连接等。
        user_table _ut;//数据库用户管理
        online_manager _om;//在线用户管理
        room_manage _rm;//房间管理
        match_manage _mm;//匹配对战管理
        session_manage _sm;//session管理

    private:
        //处理静态资源请求
        void static_res(websocketsvr::connection_ptr &con)
        {
            //1. 获取请求的URI--资源路径，了解客户端请求的页面文件名称
            websocketpp::http::parser::request req = con->get_request();//从连接对象中提取出建立连接时客户端发送的HTTP请求信息
            std::string uri = req.get_uri();//从 req 对象中提取出HTTP请求的URI，并将其存储在 uri 变量中
            //2. 组合出文件的实际路径   相对根目录 + uri
            std::string realpath = _web_root + uri;
            //3. 如果请求的是个目录，增加一个后缀  login.html,    /  ->  /login.html
            if(realpath.back() == '/')
            {
                realpath += "login.html";
            }
            //4. 读取文件内容
            Json::Value resp_json;
            std::string body;
            bool ret = file_util::read(realpath,body);//将realpath中2内容读取到body中
            //1. 文件读取失败
            if(ret == false)
            {
                body += "<html>";
                body += "<head>";
                body += "<meta charset='UTF-8'/>";
                body += "</head>";
                body += "<body>";
                body += "<h1> Not Found </h1>";
                body += "</body>";
                con->set_status(websocketpp::http::status_code::not_found);
                con->set_body(body);
                return ;
            }
            //5. 设置响应正文
            con->set_body(body);
            con->set_status(websocketpp::http::status_code::ok);
        }
        void http_resp(websocketsvr::connection_ptr& con,bool result,
        websocketpp::http::status_code::value code,const std::string& reason)
        {
            Json::Value resp_json;
            resp_json["result"]  = result;
            resp_json["reason"]  =  reason;
            std::string resp_body;
            json_util::serialize(resp_json,resp_body);
            con->set_status(code);
            con->set_body(resp_body);
            con->append_header("Content-Type","application/json");
            return ;
        }
        //动态资源请求处理
        //处理用户注册请求---解释当用户注册发起请求时,执行这个函数
        void hanler_reg(websocketsvr::connection_ptr &con) 
        {
            websocketpp::http::parser::request req = con->get_request();//从连接对象中提取出建立连接时客户端发送的HTTP请求信息
            //1. 获取请求正文
            std::string req_body = con->get_request_body();
            //2. 对正文进行 json反序列化，得到用户名和密码
            Json::Value login_info;
            bool ret = json_util::unserialize(req_body,login_info);
            if(ret == false)
            {
                LOG(DEBUG,"反序列化注册信息失败\n");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"请求的正文格式错误");
            }
            //数据库用户新增操作
            if(login_info["username"].isNull() ||login_info["password"].isNull())
            {
                LOG(DEBUG,"用户名/密码不完整\n");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"请输入用户名和密码");
            }
            ret = _ut.insert(login_info);
            if(ret == false)
            {
                LOG(DEBUG,"向数据库插入数据失败\n");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"用户名已经被占用");
            }
            //如果成功了,返回200
            return http_resp(con,false,websocketpp::http::status_code::bad_request,"用户注册成功");
        }
        //处理用户登录请求
        void hanler_login(websocketsvr::connection_ptr &con)
        {
            //1. 获取请求正文,并进行 反序列化,得到用户名和密码
            std::string req_body = con->get_request_body();
            Json::Value login_info;
            bool ret = json_util::unserialize(req_body,login_info);
            if(ret == false)
            {
                LOG(DEBUG,"反序列化失败");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"请求正文格式错误");
            } 
            //2. 效验正文的完整性,并进行数据库的用户信息验证
            if(login_info["user_name"].isNull() || login_info["password"].isNull())
            {
                LOG(DEBUG,"用户名密码不完整");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"请输入用户名和密码");
            }
            ret = _ut.login(login_info);
            if(ret == false )
            {
                //1. 如果验证失败,返回400
                LOG(DEBUG,"用户名密码验证失败");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"请输入用户名和密码");
            }
            //3. 如果验证成功,给客户端创建session
            uint64_t uid = login_info["id"].asUInt64();
            session_ptr ssp = _sm.create_session(uid,LOGIN);
            if(ssp.get() == nullptr)
            {
                LOG(DEBUG,"创建会话失败");
                return http_resp(con,false,websocketpp::http::status_code::bad_request,"创建会话失败");
            }
            _sm.set_session_expire_time(ssp->ssid(),SESSION_TIMEOUT);
            
            con->append_header()
        }
        //处理用户信息获取功能请求
        void handler_info(websocketsvr::connection_ptr &con)
        {

        }
        void http_callback(websocketpp::connection_hdl hdl) 
        {
            websocketsvr::connection_ptr conn = _websock.get_con_from_hdl(hdl);//获取连接对象
            websocketpp::http::parser::request req = conn->get_request();//从连接对象中提取出建立连接时客户端发送的HTTP请求信息
            std::string method = req.get_method();//从 req 对象中提取出HTTP请求方法，并将其存储在 method 变量中
            std::string uri = req.get_uri();//从 req 对象中提取出HTTP请求的URI，并将其存储在 uri 变量中
            if (method == "POST" && uri == "/reg") 
            {
                return hanler_reg(conn);
            }else if (method == "POST" && uri == "/login") 
            {
                return hanler_login(conn);
            }else if (method == "GET" && uri == "/info") 
            {
                return handler_info(conn);
            }else 
            {
                return static_res(conn);
            }    
        }
        void wbopen_callback(websocketpp::connection_hdl hdl) 
        {}
        void wbclose_callback(websocketpp::connection_hdl hdl) 
        {}
        void wbmessage_callback(websocketpp::connection_hdl hdl,websocketsvr::message_ptr msg) 
        {}
    public:
        gomoku_server(const std::string &host,
               const std::string &username,
               const std::string &password,
               const std::string &dbname,
               uint16_t port = 3306,
               const std::string& wwwroot = WWWROOT)
               :_web_root(wwwroot),
               _ut(host,username,password,dbname,port),
               _rm(&_ut,&_om),
               _mm(&_rm, &_ut, &_om),
               _sm(&_websock)
        {
            _websock.set_access_channels(websocketpp::log::alevel::none);
            _websock.init_asio();
            _websock.set_reuse_addr(true);
            _websock.set_http_handler(std::bind(&gomoku_server::http_callback, this, std::placeholders::_1));
            _websock.set_open_handler(std::bind(&gomoku_server::wbopen_callback, this, std::placeholders::_1));
            _websock.set_close_handler(std::bind(&gomoku_server::wbclose_callback, this, std::placeholders::_1));
            _websock.set_message_handler(std::bind(&gomoku_server::wbmessage_callback, this, std::placeholders::_1, std::placeholders::_2));
        }
        //启动服务器
        void start(int port)
        {
            // 监听端口
            _websock.listen(port);
            // 开始接收tcp连接
            _websock.start_accept();
            // 开始运行服务器
            _websock.run();
        }

};